// Copyright [2020] <unknown>
#include <bits/stdc++.h>
using namespace std;
#define ONLINE_JUDGE
#ifndef ONLINE_JUDGE
#define dbg(x...) { cerr << "\033[32;1m" << #x << " -> "; err(x); }
void err() { cerr << "\033[39;0m" << endl; }
template<typename T, typename... A>
void err(T a, A... x) { cerr << a << ' '; err(x...); }
#else
#define dbg(...)
#endif

#define sz(x) ((int)x.size())

typedef long long LL;

const int N = 1e5+50, M = 55;

vector<int> G[N];

vector<int> G2[N];

vector<int> G3[N];

void add(int u, int v, vector<int> G[]) {
    // dbg(u, v);
    G[u].push_back(v);
}


vector<int> bcc[N];
int B, bl[N];
namespace tarjan {
    int low[N], dfn[N], clk;
    void init(int n) {
        B = clk = 0;
        memset(dfn, 0, sizeof(int) * (n+1));
        for (int i=0; i<n; ++i) bcc[i].clear();
    }

    void tarjan(int u) {
        static int st[N], p;
        static bool in[N];
        dfn[u] = low[u] = ++clk;
        st[p++] = u; in[u] = true;
        for (int &v : G[u]) {
            if (!dfn[v]) {
                tarjan(v);
                low[u] = min(low[u], low[v]);
            } else if (in[v]) low[u] = min(low[u], dfn[v]);
        }
        if (dfn[u] == low[u]) {
            while (1) {
                int x = st[--p]; in[x] = false;
                bl[x] = B; bcc[B].push_back(x);
                if (x == u) break;
            }
            ++ B;
        }
    }

    void go(int n) {
        init(n);
        for (int i=0; i<n; ++i) {
            if (!dfn[i]) tarjan(i);
        }
    }
}

pair<int, int> e[N];
int n, m, d;

int vis[N][M];
bool val[N][M];
char op[N][M];


void dfs(int u, int j, int col, vector<int> G[]) {
    vis[u][j] = col;
    dbg(u, j, vis[u][j]);

    for (int v : G[u]) {
        if (!vis[v][(j+1)%d])
            dfs(v, (j+1)%d, col, G);
    }
}
int col[N][M];
int dp2[N][M];
int tot[N];
void doit(int bid, vector<int> G[]) {
    
    int *c = col[bid];
    int col = 0;



    vector<int> &v = bcc[bid];
    int n = v.size();
    // static int c[M];

    for (int st : v) {
        for (int j = 0; j < d; ++j) {
            if (!vis[st][j]) {
                dfs(st, j, ++col, G);
            }
        }
    }

    static bool got[M][N];
    for (int j=0; j<d; ++j)
        for (int st : v) {
            got[vis[st][j]][st] |= op[st][j] == '1';
        }

    for (int st : v) {
        for (int i=1; i<=col; ++i)
            c[i] += got[i][st];
    }

    for (int st : v)
        for (int j=0; j<d; ++j)
            got[vis[st][j]][st] = 0;
    
    for (int st : v)
        for (int j = 0; j < d; ++j) {
            dp2[st][j] = c[vis[st][j]];
            dbg(st, j, dp2[st][j]);
        }
    tot[bid] = col;
    for (int i=1; i<=col; ++i)
        dbg(c[i]);
}

inline void update(int &a, int b) {
    a = max(a, b);
}

int topo(int n, int B, vector<int> G[]) {
    static int deg[N];
    static int dp[N][M];
    static vector<int> rev[N];
    queue<int> Q;

    for (int i=0; i<n; ++i) {
        deg[bl[i]] += G[i].size();
        for (int v : G[i])
            rev[v].push_back(i);
    }
    for (int i=0; i<B; ++i)
        if (!deg[i]) {
            Q.push(i);
        }
    while (!Q.empty()) {
        int now = Q.front(); Q.pop();
        dbg(now);

        static bool vi[N];
        memset(vi, 0, sizeof(bool) * (tot[now]+1));
        for (int bx : bcc[now]) {
            for (int j=0; j<d; ++j) {
                if (!vi[vis[bx][j]]) {
                    vi[vis[bx][j]] = 1;
                    dp[now][vis[bx][j]] += dp2[bx][j];
                }
            }
        }
        for (int u : bcc[now])
            for (int v : rev[u]) {
                int bid = bl[v];
                --deg[bid];
                if (deg[bid] == 0)
                    Q.push(bid);

                for (int i=0; i<d; ++i) {
                    int prevd = (i-1+d)%d;
                    if (u == 1 && v == 0 && prevd == 0) {
                        dbg(bid, vis[v][prevd], now, vis[u][i], dp[now][vis[u][i]]);
                    }
                    update(dp[bid][vis[v][prevd]], dp[now][vis[u][i]]);
                }
            }
        
    }

    // dbg(dp[0][vis[0][0]]);
    for (int i=0; i<n; ++i)
        for (int j=0; j<d; ++j)
            dbg(i, j, dp2[i][j], vis[i][j]);
    for (int i=0; i<B; ++i)
        for (int j=0; j<d; ++j)
            dbg(i, j, dp[i][j]);

    dbg(vis[0][0], dp[0][3]);
    return dp[bl[0]][vis[0][0]];
}

int main(int argc, char const *argv[]) {
    // code
    scanf("%d%d%d", &n, &m, &d);
    for (int i=0; i<m; ++i) {
        scanf("%d%d", &e[i].first, &e[i].second);
        --e[i].first; --e[i].second;
        add(e[i].first, e[i].second, G);
    }

    for (int i=0; i<n; ++i) {
        scanf("%s", op[i]);
        for (int j=0; j<d; ++j) {
            if (op[i][j] == '1')
                val[i][j] = 1;
        }
    }

    tarjan::go(n);

    // =========
    for (int i=0; i<B; ++i)
        for (int v : bcc[i])
            dbg(i, v);
    // =========

    for (int i=0; i<m; ++i) {
        if (bl[e[i].first] == bl[e[i].second])
            add(e[i].first, e[i].second, G2);
        else
            add(e[i].first, e[i].second, G3);
    }

    for (int i=0; i<B; ++i)
        doit(i, G2);
    

    int ans = topo(n, B, G3);

    printf("%d\n", ans);

    return 0;
}
